﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ATM
{
    /// <summary>
    /// Module part, this should take care of all the functions regarding the ATM.
    /// Databases are excluded for data protection... no direct access was also given for this same reason.
    /// </summary>
    class Module
    {
        int CurrentAccountIndex = -1; //< the index of the currently opened account, -1 if no account is open
        
        /// <summary>
        /// Logout method, returns the account index to -1 as a defense method.
        /// </summary>
        public void logout()
        {
            CurrentAccountIndex = -1;
            Database.Logout();
        }

        /// <summary>
        /// This method returns the balance of the currently opened account.
        /// It assumes there is an opened account already.
        /// </summary>
        /// <returns>The amount of money being on the opened account.</returns>
        public int getBalance()
        {
            return Database.ListAccounts[CurrentAccountIndex].getBalance();
        }

        /// <summary>
        /// Login method, it'll go through on all already made accounts, check their account numbers,
        /// if it founds the account entered into InputAccess, it calls the subroutine of the database
        /// to validate the login... returns the value of that subroutine.
        /// 
        /// If the account doesn't exist, it creates one based on the account string,
        /// and recursively calls itself since it will exist now.
        /// 
        /// If the login was successful it sets CurrentAccountIndex to the opened account,
        /// all the other functions will not check if that's valid
        /// to give the accounts some kind of protection (since logout will set it to -1 anyways).
        /// </summary>
        /// <param name="InputAccess">Inputted bank account number</param>
        /// <param name="InputPIN">Inputted PIN code</param>
        /// <returns>Returns a boolean value, true if login was successful, false otherwise</returns>
        public bool login(string InputAccess, string InputPIN)
        {
            //check for Lengths
            if (InputPIN.Length != 4 || InputAccess.Length != 16){
                return false;
            }

            //go through in decrementing order... due to recursion calling
            for (int i = Database.ListAccounts.Count - 1; i > -1; i--)
            {
                if (String.Compare(InputAccess, 0, Database.ListAccounts[i].getAccountID(), 0, InputAccess.Length) == 0)
                {
                    //ok, found the account, try to log in
                    if (Database.ListAccounts[i].CheckPIN(InputPIN))
                    {
                        //success!
                        CurrentAccountIndex = i;
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            //not found yet? create it!
            Database.ListAccounts.Add(new Database(InputAccess));

            //and check it, since it's last one, the for cycle will return the boolean early
            return login (InputAccess, InputPIN);

        }

        /// <summary>
        /// This function changes an account's PIN code
        /// </summary>
        /// <param name="oldPIN">Old PIN code</param>
        /// <param name="newPIN">New PIN code</param>
        /// <returns>True if change was successful, false if not.</returns>
        public bool ChangePIN(string oldPIN, string newPIN)
        {
            int Temp;

            if (!int.TryParse(oldPIN, out Temp) || !int.TryParse(newPIN, out Temp) || oldPIN.Length != 4 || newPIN.Length != 4)
            {
                return false;
            }

            return Database.ListAccounts[CurrentAccountIndex].ChangePIN(oldPIN, newPIN);
        }

        /// <summary>
        /// This function tries to take out an amount of money from the already opened account.
        /// 
        /// If possible it gives out the money and deduce it from the account.
        /// </summary>
        /// <param name="Amount">The amount of money it should take.</param>
        /// <returns>Returns a boolean, true, if there were enough reserves
        /// (so GUI can actually give out the amount) false, if not.</returns>
        public bool TakeCash(int Amount)
        {
            if (Amount > Database.ListAccounts[CurrentAccountIndex].getBalance())
            {
                return false;
            }
            else
            {
                Database.ListAccounts[CurrentAccountIndex].TakeCash(Amount);
                return true;
            }
        }
    }
}
